import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
%%html
<style>
table {float:left}
</style>
df = pd.read_csv('train.csv')
df.head()
| id | gender | age | hypertension | heart_disease | ever_married | work_type | Residence_type | avg_glucose_level | bmi | smoking_status | stroke | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | Male | 28.0 | 0 | 0 | Yes | Private | Urban | 79.53 | 31.1 | never smoked | 0 |
| 1 | 1 | Male | 33.0 | 0 | 0 | Yes | Private | Rural | 78.44 | 23.9 | formerly smoked | 0 |
| 2 | 2 | Female | 42.0 | 0 | 0 | Yes | Private | Rural | 103.00 | 40.3 | Unknown | 0 |
| 3 | 3 | Male | 56.0 | 0 | 0 | Yes | Private | Urban | 64.87 | 28.8 | never smoked | 0 |
| 4 | 4 | Female | 24.0 | 0 | 0 | No | Private | Rural | 73.36 | 28.8 | never smoked | 0 |
Variável | Descrição |:-- | :-- | Gender| Gênero Age | Idade Hypertension | Indivíduo tem ou não tem hipertensão Heart_Disease | Indivíduo tem ou não tem doença no coração Ever_Married | Indivíduo já se casou ou não Work_Type | Setor/Tipo de trabalho do profissional Residence_type | Zona urbana ou rural Avg_Glucose_Level | Nível médio de glicose Smoking_Status | Nível de tabagismo Stroke | Teve AVC ou não
df.describe()
| id | age | hypertension | heart_disease | avg_glucose_level | bmi | stroke | |
|---|---|---|---|---|---|---|---|
| count | 15304.000000 | 15304.000000 | 15304.000000 | 15304.000000 | 15304.000000 | 15304.000000 | 15304.000000 |
| mean | 7651.500000 | 41.417708 | 0.049726 | 0.023327 | 89.039853 | 28.112721 | 0.041296 |
| std | 4418.028595 | 21.444673 | 0.217384 | 0.150946 | 25.476102 | 6.722315 | 0.198981 |
| min | 0.000000 | 0.080000 | 0.000000 | 0.000000 | 55.220000 | 10.300000 | 0.000000 |
| 25% | 3825.750000 | 26.000000 | 0.000000 | 0.000000 | 74.900000 | 23.500000 | 0.000000 |
| 50% | 7651.500000 | 43.000000 | 0.000000 | 0.000000 | 85.120000 | 27.600000 | 0.000000 |
| 75% | 11477.250000 | 57.000000 | 0.000000 | 0.000000 | 96.980000 | 32.000000 | 0.000000 |
| max | 15303.000000 | 82.000000 | 1.000000 | 1.000000 | 267.600000 | 80.100000 | 1.000000 |
Aparentemente, não é possivel observar nenhum dado inconsistente.
df.isnull().sum()
id 0 gender 0 age 0 hypertension 0 heart_disease 0 ever_married 0 work_type 0 Residence_type 0 avg_glucose_level 0 bmi 0 smoking_status 0 stroke 0 dtype: int64
Não foi encontrando nenhum valor nulo no conjunto de dados.
df.head()
| id | gender | age | hypertension | heart_disease | ever_married | work_type | Residence_type | avg_glucose_level | bmi | smoking_status | stroke | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | Male | 28.0 | 0 | 0 | Yes | Private | Urban | 79.53 | 31.1 | never smoked | 0 |
| 1 | 1 | Male | 33.0 | 0 | 0 | Yes | Private | Rural | 78.44 | 23.9 | formerly smoked | 0 |
| 2 | 2 | Female | 42.0 | 0 | 0 | Yes | Private | Rural | 103.00 | 40.3 | Unknown | 0 |
| 3 | 3 | Male | 56.0 | 0 | 0 | Yes | Private | Urban | 64.87 | 28.8 | never smoked | 0 |
| 4 | 4 | Female | 24.0 | 0 | 0 | No | Private | Rural | 73.36 | 28.8 | never smoked | 0 |
fig = px.pie(df,
names='gender',
color='gender',
hole=0.5,
color_discrete_map={'Male':'darkblue',
'Female':'pink',
'Other':'red'})
fig.update_layout(
title_text="Proporção de Indivíduos por Gênero",
annotations=[dict(text='Gênero', x=0.5, y=0.5, font_size=20, showarrow=False)])
fig.show()
A maioria dos indivíduos do conjunto de dados são mulheres, cerca de 61,7% dos indivíduos, seguido pelos homens com 38,3% e outros com uma pequena porcentagem dos dados.
df['age'].describe()
count 15304.000000 mean 41.417708 std 21.444673 min 0.080000 25% 26.000000 50% 43.000000 75% 57.000000 max 82.000000 Name: age, dtype: float64
A idade média dos indivíduos do grupo foi de 41.41 anos, com um desvio padrão de por volta de 21.44 e uma mediana igual a 43.
import plotly.figure_factory as ff
df = df[df['age'] > 2]
hist_data = [df['age'].values]
group_labels = ['Idade'] # name of the dataset
fig = ff.create_distplot(hist_data,
group_labels,
colors=['#473db3'])
fig.show()
É possível observar uma distribuição de idade dispersa.
fig = px.pie(df['hypertension'].replace({0:'Não Hipertenso', 1:'Hipertenso'}),
names='hypertension',
color='hypertension',
hole=0.5,
color_discrete_map={'Não Hipertenso':'#149692',
'Hipertenso':'red'})
fig.update_layout(
title_text="Proporção de Indivíduos por Diagnóstico de Hipertensão",
annotations=[dict(text='Hipertensão', x=0.5, y=0.5, font_size=20, showarrow=False)])
fig.show()
fig = px.bar(df['heart_disease'].value_counts().to_frame().reset_index().replace({0:'Não', 1:'Sim'}),
x="heart_disease",
y="count",
text_auto='.5s',
color = "heart_disease",
color_discrete_map={'Não':'#03a5fc',
'Sim':'red'})
fig.update_layout({
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
}, title='Quantidade de indivíduos com e sem doença no coração')
fig.update_yaxes(title='Quantidade')
fig.update_xaxes(title='Doença no coração')
fig.update_traces(textfont_size=14,
textangle=0,
textposition="outside")
fig.show()
fig = px.pie(df['ever_married'].replace({'Yes':'Sim', 'No':'Não'}),
names='ever_married',
color='ever_married',
hole=0.5,
color_discrete_map={'Não':'black',
'Sim':'red'})
fig.update_layout(
title_text="Já casou ou é casado?",
annotations=[dict(text='Casamento', x=0.5, y=0.5, font_size=20, showarrow=False)])
fig.update_traces(textposition='inside', textinfo='percent+label')
fig.show()
df_profissional = (df['work_type'].str.get_dummies().sum().sort_values(ascending=False) / df.shape[0]).to_frame()
df_profissional = df_profissional.rename_axis('setor_trabalhador').reset_index()
df_profissional = df_profissional.rename(columns={0:'proporcao'})
fig = px.bar(df_profissional,
x='setor_trabalhador',
y='proporcao',
text=df_profissional['proporcao'].apply(lambda x: '{:.2f}%'.format(x*100)),
color='setor_trabalhador')
fig.update_layout(xaxis={'categoryorder':'total ascending'})
fig.update_layout({
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
}, title='Proporção de profissionais por setor/tipo')
fig.update_traces(textfont_size=14,
textangle=0,
textposition="outside")
fig.update_yaxes(title='Percentual %')
fig.update_xaxes(title='Tipo de profissional')
fig.show()
df_zona = (df['Residence_type'].str.get_dummies().sum().sort_values(ascending=False) / df.shape[0]).to_frame()
df_zona = df_zona.rename_axis('zona').reset_index()
df_zona = df_zona.rename(columns={0:'proporcao'})
fig = px.bar(df_zona,
x='zona',
y='proporcao',
text=df_zona['proporcao'].apply(lambda x: '{:.2f}%'.format(x*100)),
color='zona',
color_discrete_map={'Urban':'#03a5fc',
'Rural':'#0fd156'})
fig.update_layout(xaxis={'categoryorder':'total ascending'})
fig.update_layout({
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
}, title='Proporção de indivíduos por zona')
fig.update_traces(textfont_size=14,
textangle=0,
textposition="outside")
fig.update_yaxes(title='Percentual %')
fig.update_xaxes(title='Zonas')
fig.show()
df['avg_glucose_level'].describe()
count 14719.000000 mean 89.123546 std 25.709775 min 55.220000 25% 74.920000 50% 85.150000 75% 96.860000 max 267.600000 Name: avg_glucose_level, dtype: float64
fig = px.histogram(df,
x="avg_glucose_level",
marginal="box",
color_discrete_sequence=['#0e063d'],
histnorm='probability density'
)
fig.update_yaxes(title='Densidade de Probabilidade', row=1, col=1)
fig.update_xaxes(title='Nível médio de Glicose', row=1, col=1)
fig.show()
Níveis de Glicemia | Descrição |:-- | :-- | Baixa| Igual ou inferior a 70 mg/dL. Normal | Inferior a 99 mg/dL. Alterada | Entre 100 mg/dL e 125 mg/dL. Diabetes | igual ou superior a 126 mg/dL.
condicoes = [
(df["avg_glucose_level"] <= 70),
(df["avg_glucose_level"] < 100),
(df["avg_glucose_level"] < 126),
]
escolhas = ['Glicemia Baixa', 'Glicemia Normal', 'Glicemia Alterada']
df['glicemia'] = np.select(condicoes, escolhas, default='Diabetes')
fig = px.pie(df['glicemia'],
names='glicemia',
hole = 0.5,
color='glicemia',
color_discrete_map={'Glicemia Normal': 'green',
'Glicemia Alterada':'#04033d',
'Glicemia Baixa': '#700270',
'Diabetes':'red'})
fig.update_layout(
title_text="Proporção de Indivíduos por cada Classe de Glicemia",
annotations=[dict(text='Glicemia', x=0.5, y=0.5, font_size=20, showarrow=False)])
fig.show()
df['bmi'].describe()
count 14719.000000 mean 28.476973 std 6.556298 min 10.300000 25% 24.000000 50% 27.900000 75% 32.200000 max 80.100000 Name: bmi, dtype: float64
fig = px.histogram(df,
x="bmi",
marginal="box",
color_discrete_sequence=['#0f9dd1'],
histnorm='probability density'
)
fig.update_yaxes(title='Densidade de Probabilidade', row=1, col=1)
fig.update_xaxes(title='Índice de Massa Corporal', row=1, col=1)
fig.show()
condicoes = [
(df["bmi"] < 18.5),
(df["bmi"] < 25),
(df["bmi"] < 30),
(df["bmi"] < 35),
(df["bmi"] < 40)
]
escolhas = ['Abaixo do Peso', 'Peso Normal', 'Acima do Peso', 'Obsesidade I', 'Obesidade II']
df['bmi_diagnostico'] = np.select(condicoes, escolhas, default='Obesidade III')
df_bmi = (df['bmi_diagnostico'].str.get_dummies().sum().sort_values(ascending=False) / df.shape[0]).to_frame()
df_bmi = df_bmi.rename_axis('Classe_Peso').reset_index()
df_bmi = df_bmi.rename(columns={0:'proporcao'})
fig = px.bar(df_bmi,
x='Classe_Peso',
y='proporcao',
text=df_bmi['proporcao'].apply(lambda x: '{:.2f}%'.format(x*100)),
color='Classe_Peso')
fig.update_layout({
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
}, title='Proporção de Indivíduos por Peso')
fig.update_traces(textfont_size=14,
textangle=0,
textposition="outside")
fig.update_yaxes(title='Percentual %')
fig.update_xaxes(categoryorder='array', categoryarray= ['Abaixo do Peso',
'Peso Normal',
'Acima do Peso',
'Obsesidade I',
'Obesidade II',
'Obesidade III'], title='Níveis de Cargo')
fig.show()
df.groupby('stroke')['smoking_status'].value_counts(normalize=True)
stroke smoking_status
0 never smoked 0.427344
Unknown 0.273728
formerly smoked 0.154469
smokes 0.144459
1 never smoked 0.406646
formerly smoked 0.251582
Unknown 0.170886
smokes 0.170886
Name: proportion, dtype: float64
df['smoking_status'].replace({'Unknown':'never smoked'}, inplace=True)
df_fumante = (df['smoking_status'].str.get_dummies().sum().sort_values(ascending=False) / df.shape[0]).to_frame()
df_fumante = df_fumante.rename_axis('nivel_tabagismo').reset_index()
df_fumante = df_fumante.rename(columns={0:'proporcao'})
fig = px.bar(df_fumante,
x='nivel_tabagismo',
y='proporcao',
text=df_fumante['proporcao'].apply(lambda x: '{:.2f}%'.format(x*100)),
color='nivel_tabagismo')
fig.update_layout(xaxis={'categoryorder':'total ascending'})
fig.update_layout({
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
}, title='Proporção por nível de tabagismo')
fig.update_traces(textfont_size=14,
textangle=0,
textposition="outside")
fig.update_yaxes(title='Percentual %')
fig.update_xaxes(title='Níveis de tabagismo')
fig.show()
fig = px.pie(df['stroke'].replace({1:'Sim', 0:'Não'}),
names='stroke',
color='stroke',
hole= 0.5,
color_discrete_map={'Não':'#028bed',
'Sim':'red'})
fig.update_layout(
title_text="Proporção de AVC entre os Indivíduos",
annotations=[dict(text='AVC', x=0.5, y=0.5, font_size=20, showarrow=False)])
fig.show()
df_2 = pd.DataFrame.copy(df)
df_2['ever_married'] = df_2['ever_married'].replace({'Yes':1, 'No':0})
df_2 = pd.concat([df_2, df_2['gender'].str.get_dummies()], axis=1)
df_2 = pd.concat([df_2, df_2['work_type'].str.get_dummies()], axis=1)
df_2 = pd.concat([df_2, df_2['Residence_type'].str.get_dummies()], axis=1)
df_2 = pd.concat([df_2, df_2['smoking_status'].str.get_dummies()], axis=1)
df_2 = pd.concat([df_2, df_2['glicemia'].str.get_dummies()], axis=1)
df_2 = pd.concat([df_2, df_2['bmi_diagnostico'].str.get_dummies()], axis=1)
df_2 = df_2.drop(columns=['gender', 'work_type',
'Residence_type',
'smoking_status',
'bmi',
'avg_glucose_level',
'glicemia',
'bmi_diagnostico'], axis=1)
df_2 = df_2.loc[:, ['age', 'hypertension', 'heart_disease', 'ever_married',
'Female', 'Male', 'Govt_job', 'Never_worked', 'Private',
'Self-employed', 'children', 'Rural', 'Urban', 'never smoked',
'formerly smoked', 'smokes', 'Glicemia Baixa', 'Glicemia Normal',
'Glicemia Alterada','Diabetes', 'Abaixo do Peso', 'Peso Normal',
'Acima do Peso', 'Obsesidade I', 'Obesidade II', 'Obesidade III', 'stroke']]
fig = px.imshow(df_2.corr(), text_auto='.2f', width=1000, height=800)
fig.show()
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import RandomizedSearchCV
import warnings
warnings.filterwarnings("ignore")
X = df_2.iloc[:, :-1].values
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X = scaler.fit_transform(X)
Y = df_2.iloc[:, -1].values
from sklearn.model_selection import train_test_split
X_treino, X_teste, y_treino, y_teste = train_test_split(X, Y, test_size=0.5, stratify = Y, random_state=0)
from sklearn.tree import DecisionTreeClassifier
parametros = {'criterion':['gini', 'entropy', 'log_loss'],
'splitter':["best", "random"],
'max_depth':[None, 1, 2, 5, 7, 9],
'min_samples_split':[2, 5, 7, 9],
'min_samples_leaf':[1, 2, 5, 7, 9],
'class_weight': [None, 'balanced']}
grid_search = GridSearchCV(estimator=DecisionTreeClassifier(random_state=0),
param_grid=parametros,
scoring='f1')
grid_search.fit(X_treino, y_treino)
melhores_parametros = grid_search.best_params_
melhor_resultado = grid_search.best_score_
print(melhores_parametros, melhor_resultado)
{'class_weight': 'balanced', 'criterion': 'gini', 'max_depth': 2, 'min_samples_leaf': 2, 'min_samples_split': 2, 'splitter': 'random'} 0.2892243544865901
arvore = DecisionTreeClassifier(criterion='gini',
max_depth = 2,
min_samples_leaf=92,
min_samples_split = 2,
splitter = 'random',
class_weight = 'balanced',
random_state=0)
arvore.fit(X_treino, y_treino)
DecisionTreeClassifier(class_weight='balanced', max_depth=2,
min_samples_leaf=92, random_state=0, splitter='random')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. DecisionTreeClassifier(class_weight='balanced', max_depth=2,
min_samples_leaf=92, random_state=0, splitter='random')previsoes_arvore = arvore.predict(X_teste)
previsoes_arvore_proba = arvore.predict_proba(X_teste)
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
import seaborn as sns
sns.heatmap(confusion_matrix(y_teste, previsoes_arvore), annot=True, fmt='g')
plt.title('Matriz de Confusão')
plt.show()
print(classification_report(y_teste, previsoes_arvore))
precision recall f1-score support
0 0.98 0.90 0.94 7044
1 0.21 0.59 0.31 316
accuracy 0.89 7360
macro avg 0.60 0.75 0.63 7360
weighted avg 0.95 0.89 0.91 7360
from sklearn.ensemble import RandomForestClassifier
parametros = {'criterion':['gini', 'entropy', 'log_loss'],
'max_depth':[None, 1, 2, 5, 7, 9],
'min_samples_split':[2, 5, 7, 9],
'min_samples_leaf':[1, 2, 5, 7, 9],
'class_weight': ['balanced', 'balanced_subsample'],
'max_features': ['sqrt', 'log2', None]
}
rand = RandomizedSearchCV(estimator=RandomForestClassifier(random_state=0),
param_distributions=parametros,
cv=20,
scoring='f1')
rand.fit(X_treino, y_treino)
RandomizedSearchCV(cv=20, estimator=RandomForestClassifier(random_state=0),
param_distributions={'class_weight': ['balanced',
'balanced_subsample'],
'criterion': ['gini', 'entropy',
'log_loss'],
'max_depth': [None, 1, 2, 5, 7, 9],
'max_features': ['sqrt', 'log2', None],
'min_samples_leaf': [1, 2, 5, 7, 9],
'min_samples_split': [2, 5, 7, 9]},
scoring='f1')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. RandomizedSearchCV(cv=20, estimator=RandomForestClassifier(random_state=0),
param_distributions={'class_weight': ['balanced',
'balanced_subsample'],
'criterion': ['gini', 'entropy',
'log_loss'],
'max_depth': [None, 1, 2, 5, 7, 9],
'max_features': ['sqrt', 'log2', None],
'min_samples_leaf': [1, 2, 5, 7, 9],
'min_samples_split': [2, 5, 7, 9]},
scoring='f1')RandomForestClassifier(random_state=0)
RandomForestClassifier(random_state=0)
rand.best_params_
{'min_samples_split': 5,
'min_samples_leaf': 9,
'max_features': None,
'max_depth': None,
'criterion': 'entropy',
'class_weight': 'balanced'}
random_forest = RandomForestClassifier(criterion='entropy',
min_samples_leaf = 9,
min_samples_split= 5,
max_depth = None,
class_weight = 'balanced',
random_state=0)
random_forest.fit(X_treino, y_treino)
RandomForestClassifier(class_weight='balanced', criterion='entropy',
min_samples_leaf=9, min_samples_split=5, random_state=0)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. RandomForestClassifier(class_weight='balanced', criterion='entropy',
min_samples_leaf=9, min_samples_split=5, random_state=0)previsoes_random = random_forest.predict(X_teste)
previsoes_random_proba = random_forest.predict_proba(X_teste)
sns.heatmap(confusion_matrix(y_teste, previsoes_random), annot=True, fmt='g')
plt.title('Matriz de Confusão')
plt.show()
print(classification_report(y_teste, previsoes_random))
precision recall f1-score support
0 0.98 0.85 0.91 7044
1 0.17 0.69 0.27 316
accuracy 0.84 7360
macro avg 0.58 0.77 0.59 7360
weighted avg 0.95 0.84 0.88 7360
from sklearn.neighbors import KNeighborsClassifier
parametros = {'n_neighbors': [5, 9, 13],
'weights': ['uniform', 'distance'],
'algorithm': ['auto', 'ball_tree', 'kd_tree', 'brute'],
'p': [1, 2],
'metric':['manhattan', 'minkowski', 'l1', 'l2']}
grid_search = GridSearchCV(estimator=KNeighborsClassifier(),
param_grid=parametros,
scoring='f1')
grid_search.fit(X_treino, y_treino)
melhores_parametros = grid_search.best_params_
melhor_resultado = grid_search.best_score_
print(melhores_parametros, melhor_resultado)
{'algorithm': 'auto', 'metric': 'manhattan', 'n_neighbors': 5, 'p': 1, 'weights': 'distance'} 0.13307656723005487
knn = KNeighborsClassifier(algorithm = 'auto',
n_neighbors = 5,
metric = 'manhattan',
p = 1,
weights ='distance')
knn.fit(X_treino, y_treino)
KNeighborsClassifier(metric='manhattan', p=1, weights='distance')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
KNeighborsClassifier(metric='manhattan', p=1, weights='distance')
previsoes_knn = knn.predict(X_teste)
previsoes_knn_proba = knn.predict_proba(X_teste)
sns.heatmap(confusion_matrix(y_teste, previsoes_knn), annot=True, fmt='g')
plt.title('Matriz de Confusão')
plt.show()
print(classification_report(y_teste, previsoes_knn))
precision recall f1-score support
0 0.96 0.99 0.97 7044
1 0.26 0.10 0.14 316
accuracy 0.95 7360
macro avg 0.61 0.54 0.56 7360
weighted avg 0.93 0.95 0.94 7360
from sklearn.linear_model import LogisticRegression
parametros = {'penalty':['l1', 'l2'],
'fit_intercept': [True, False],
'solver':['lbfgs', 'liblinear', 'newton-cg', 'newton-cholesky', 'sag', 'saga'],
'max_iter':[100, 125, 150],
'class_weight': [None, 'balanced'],
'warm_start': [True, False]}
grid_search = GridSearchCV(estimator=LogisticRegression(random_state=0),
param_grid=parametros,
scoring='f1')
grid_search.fit(X_treino, y_treino)
melhores_parametros = grid_search.best_params_
melhor_resultado = grid_search.best_score_
print(melhores_parametros, melhor_resultado)
{'class_weight': 'balanced', 'fit_intercept': False, 'max_iter': 150, 'penalty': 'l2', 'solver': 'sag', 'warm_start': True} 0.24867748977149998
reg_log = LogisticRegression(penalty = 'l2',
fit_intercept = False,
solver = 'sag',
max_iter = 150,
class_weight = 'balanced',
warm_start = True,
random_state=0)
reg_log.fit(X_treino, y_treino)
LogisticRegression(class_weight='balanced', fit_intercept=False, max_iter=150,
random_state=0, solver='sag', warm_start=True)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. LogisticRegression(class_weight='balanced', fit_intercept=False, max_iter=150,
random_state=0, solver='sag', warm_start=True)previsoes_reg_log = reg_log.predict(X_teste)
previsoes_reg_log_proba = reg_log.predict_proba(X_teste)
sns.heatmap(confusion_matrix(y_teste, previsoes_reg_log), annot=True, fmt='g')
<Axes: >
print(classification_report(y_teste, previsoes_reg_log))
precision recall f1-score support
0 0.99 0.65 0.79 7044
1 0.10 0.90 0.19 316
accuracy 0.66 7360
macro avg 0.55 0.77 0.49 7360
weighted avg 0.95 0.66 0.76 7360
import matplotlib.pyplot as plt
from sklearn.metrics import roc_auc_score, RocCurveDisplay
from sklearn.metrics import precision_recall_curve, PrecisionRecallDisplay
fig, ax = plt.subplots(figsize=(8,8))
RocCurveDisplay.from_predictions(y_teste, previsoes_arvore_proba[:, 1], ax=ax, name='Árvore de Decisão')
RocCurveDisplay.from_predictions(y_teste, previsoes_random_proba[:, 1], ax=ax, name='Random_Forest')
RocCurveDisplay.from_predictions(y_teste, previsoes_knn_proba[:, 1], ax=ax, name='KNN')
RocCurveDisplay.from_predictions(y_teste, previsoes_reg_log_proba[:, 1], ax=ax, name='Regressão_Logistica');
ax.set_title('Curva ROC')
ax.set_xlabel('1 - Especificidade (Taxa de Falso Positivo)')
ax.set_ylabel('Sensibilidade');
ax.grid()
fig, ax = plt.subplots(figsize=(8,8))
PrecisionRecallDisplay.from_predictions(y_teste, previsoes_arvore_proba[:, 1], ax=ax, name='Árvore de Decisão')
PrecisionRecallDisplay.from_predictions(y_teste, previsoes_random_proba[:, 1], ax=ax, name='Random_Forest')
PrecisionRecallDisplay.from_predictions(y_teste, previsoes_knn_proba[:, 1], ax=ax, name='KNN')
PrecisionRecallDisplay.from_predictions(y_teste, previsoes_reg_log_proba[:, 1], ax=ax, name='Regressão_Logistica');
ax.set_title('Curva Precisão-Especificidade')
ax.set_xlabel('Especificidade')
ax.set_ylabel('Precisão');
plt.legend(loc='upper right')
ax.grid()
from sklearn.model_selection import cross_val_score, KFold
import sklearn.metrics as sk
from tqdm import tqdm
resultados_arvore = []
resultados_random_forest = []
resultados_knn = []
resultados_reg_log = []
from sklearn.model_selection import StratifiedKFold
with tqdm(total=100) as barra:
for i in range(30):
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=i)
arvore = DecisionTreeClassifier(criterion='gini',
max_depth = None,
min_samples_leaf=2,
min_samples_split = 7,
splitter = 'best',
class_weight = 'balanced')
scores = cross_val_score(arvore, X, Y, cv=kfold, scoring='f1')
resultados_arvore.append(scores.mean())
random_forest = RandomForestClassifier(criterion='gini',
min_samples_leaf = 7,
min_samples_split= 7,
max_depth = None,
class_weight = 'balanced')
scores = cross_val_score(random_forest, X, Y, cv=kfold, scoring='f1')
resultados_random_forest.append(scores.mean())
reg_log = LogisticRegression(penalty = 'l2',
fit_intercept = True,
solver = 'lbfgs',
max_iter = 100,
class_weight = 'balanced',
warm_start = True)
scores = cross_val_score(reg_log, X, Y, cv=kfold, scoring='f1')
resultados_reg_log.append(scores.mean())
knn = KNeighborsClassifier(algorithm = 'auto',
n_neighbors= 5,
p = 2,
weights ='distance')
scores = cross_val_score(knn, X, Y, cv=kfold, scoring='f1')
resultados_knn.append(scores.mean())
barra.update(100/30)
100%|█████████████████████████████████████████████████████████████████▉| 99.99999999999997/100 [04:26<00:00, 2.67s/it]
A ideia desse código é pegar 30 amostras de valores médios do f1 macro para cada modelo, para isso foi utilizado StratifiedKFold visando manter a proporção da variável alvo dentro de cada fold de treino e teste.
resultados = pd.DataFrame({'Arvore': resultados_arvore,
'Random_Forest': resultados_random_forest,
'KNN': resultados_knn,
'Regressao_Logistica': resultados_reg_log})
fig = px.bar(resultados.mean(), color=resultados.columns)
fig.update_layout({
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
}, title='Valor médio obtido para F1 para Cada Modelo')
fig.update_yaxes(title='Percentual %')
fig.update_xaxes(title='Modelo')
fig.update_layout(showlegend=False)
fig.show()
fig = px.bar((resultados.std() / resultados.mean()), color=resultados.columns)
fig.update_layout({
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
}, title='Coeficiente de Variação para do F1 para cada Modelo')
fig.update_yaxes(title='Percentual %')
fig.update_xaxes(title='Modelo')
fig.update_layout(showlegend=False)
fig.show()
from scipy.stats import shapiro
from tabulate import tabulate
Caso o p-valor seja > 0.05, pode-se dizer que a distribuição dos valores se assemelha a uma normal.
teste_normal = {'Árvore de Decisão': shapiro(resultados_arvore)[1],
'Random Forest': shapiro(resultados_random_forest)[1],
'KNN': shapiro(resultados_knn)[1],
'Regressão Logística': shapiro(resultados_reg_log)[1]}
print(tabulate(teste_normal.items(), headers=['Classificador', 'P-valor'], tablefmt='psql'))
+---------------------+-----------+ | Classificador | P-valor | |---------------------+-----------| | Árvore de Decisão | 0.841821 | | Random Forest | 0.848397 | | KNN | 0.803851 | | Regressão Logística | 0.244158 | +---------------------+-----------+
tukey_df = pd.melt(resultados,
value_vars=['Arvore', 'Random_Forest', 'KNN', 'Regressao_Logistica']).rename(columns={'variable':'Algoritmo',
'value':'F1'})
from statsmodels.stats.multicomp import MultiComparison
compara_algoritmos = MultiComparison(tukey_df['F1'], tukey_df['Algoritmo'])
Se o p-valor < 0.05, os resultados dos algoritmos são diferentes.
teste_estatistico = compara_algoritmos.tukeyhsd()
print(teste_estatistico)
Multiple Comparison of Means - Tukey HSD, FWER=0.05
=======================================================================
group1 group2 meandiff p-adj lower upper reject
-----------------------------------------------------------------------
Arvore KNN -0.0894 0.0 -0.0929 -0.0859 True
Arvore Random_Forest 0.0659 0.0 0.0624 0.0694 True
Arvore Regressao_Logistica 0.0264 0.0 0.0229 0.0299 True
KNN Random_Forest 0.1553 0.0 0.1518 0.1588 True
KNN Regressao_Logistica 0.1158 0.0 0.1123 0.1193 True
Random_Forest Regressao_Logistica -0.0394 0.0 -0.0429 -0.036 True
-----------------------------------------------------------------------
teste_estatistico.plot_simultaneous();
X = df_2.iloc[:, :-1]
X['age'] = scaler.fit_transform(X['age'].values.reshape(-1, 1))
Y = df_2.iloc[:, -1]
from sklearn.model_selection import train_test_split
X_treino, X_teste, y_treino, y_teste = train_test_split(X, Y, test_size=0.5, stratify = Y, random_state=0)
import lime
from lime import lime_tabular
classificadores = ['Random Forest', 'Decision Tree', 'KNN', 'Logistic Regression']
modelos = [random_forest, arvore, knn, reg_log]
for i, pipe in enumerate(modelos):
print(classificadores[i])
modelo = pipe.fit(X_treino, y_treino)
test = X_teste.iloc[4]
lime_explainer = lime_tabular.LimeTabularExplainer(
training_data=np.array(X_treino),
feature_names=X_treino.columns,
class_names=['não AVC', 'AVC'],
mode='classification'
)
lime_exp = lime_explainer.explain_instance(
data_row=test,
predict_fn=modelo.predict_proba
)
lime_exp.show_in_notebook(show_table=True)
Random Forest
Decision Tree
KNN
Logistic Regression
import shap
explainer = shap.TreeExplainer(random_forest)
shap_values = explainer.shap_values(X_teste)
shap.summary_plot(shap_values, X_teste, plot_type='bar', max_display=15)
import shap
explainer = shap.LinearExplainer(reg_log, X)
shap_values = explainer.shap_values(X_teste)
shap.summary_plot(shap_values, X_teste, max_display=15)